package muni.fi.bookscan;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

public class SearchTask extends AsyncTask<String,Void,List<List<String>>>{
	
	private ProgressDialog searchingDialog;
	private Activity activity;
	private Context context;
	   	
	/** Constructor, initialization of the searchingDialog and MainActivity */
	public SearchTask(Activity activity){
		this.activity = activity;
		context = activity;
		searchingDialog = new ProgressDialog(context);		
	}
	
	/** Showing the progress Searching dialog onPreExecute */
	protected void onPreExecute(){
		this.searchingDialog.setMessage("Searching...");
		this.searchingDialog.show();
	}
	
	/** Dismissing dialog and showing the book name */
	protected void onPostExecute(final List<List<String>> allItemsInfo){
		if(this.searchingDialog.isShowing()){
			this.searchingDialog.dismiss();
		}
		
		((MainActivity) activity).setUpBookList(allItemsInfo);
		//TextView pomText = (TextView)activity.findViewById(R.id.input);
		//pomText.setText(bookName);
	}
	
	/** Searching the book on the Google Books */
	protected List<List<String>> doInBackground(String... code){
		
		//String bookName = "";
		List<List<String>> allItemsInfo = new ArrayList<List<String>>();
		
		try {

			//Setting up SSL connection
			code[0] = code[0].replace(' ', '+');
			URL url;
			if(code[0].matches("[0-9]+")){//only number --> isbn
				url = new URL("https://www.googleapis.com/books/v1/volumes?q=isbn:"+code[0]);
			} else {//text --> search everything
				url = new URL("https://www.googleapis.com/books/v1/volumes?q="+code[0]);
			}
			HttpURLConnection http = null;
			
	        if (url.getProtocol().toLowerCase().equals("https")) {
	            trustAllHosts();
	                HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
	                https.setHostnameVerifier(DO_NOT_VERIFY);
	                http = https;
	        } else {
	                http = (HttpURLConnection) url.openConnection();
	        }
			
			//Changing input stream into string
	        BufferedReader r = new BufferedReader(new InputStreamReader(http.getInputStream()));
			StringBuilder total = new StringBuilder();
			String line = null;
			
			while ((line = r.readLine()) != null) {
			    total.append(line);
			}
			
			//Parsing JSON output
			JSONObject jObject = new JSONObject(total.toString());
			int itemsCount = jObject.getInt("totalItems");
			if (itemsCount == 0) return allItemsInfo;
			
			//Storing search results
			JSONArray items = jObject.getJSONArray("items");
			for (int i = 0; i < itemsCount; i++) {
				List<String> bookInfo = new ArrayList<String>();
				JSONObject current = items.getJSONObject(i).getJSONObject("volumeInfo");
				
				String temp = "";
				bookInfo.add(current.getString("title"));
				
				if (current.has("authors")) {
					temp = current.getJSONArray("authors").toString();
					temp = temp.substring(1, temp.length() - 1);
					temp = temp.replace("\"", "");
					temp = temp.replace(",", ", ");
					bookInfo.add(temp);
				} else {
					bookInfo.add("N/A");
				}
				
				if (current.has("publisher")) {
					bookInfo.add(current.getString("publisher"));
				} else {
					bookInfo.add("N/A");
				}
				
				if (current.has("publishedDate")) {
					bookInfo.add(current.getString("publishedDate"));
				} else {
					bookInfo.add("N/A");
				}
				
				if (current.has("description")) {
					bookInfo.add(current.getString("description"));
				} else {
					bookInfo.add("N/A");
				}
				
				if (current.has("pageCount")) {
					bookInfo.add(current.getString("pageCount"));
				} else {
					bookInfo.add("N/A");
				}
				
				if (current.has("categories")) {
					temp = current.getJSONArray("categories").toString();
					temp = temp.substring(1, temp.length() - 1);
					temp = temp.replace("\"", "");
					temp = temp.replace(",", ", ");
					bookInfo.add(temp);
				} else {
					bookInfo.add("N/A");
				}
				
				if (current.has("averageRating")) {
					bookInfo.add(Double.toString(current.getDouble("averageRating")));
				} else {
					bookInfo.add("N/A");
				}
				
				if (current.has("ratingsCount")) {
					bookInfo.add(Integer.toString(current.getInt("ratingsCount")));
				} else {
					bookInfo.add("0");
				}
				
				if (current.has("language")) {
					bookInfo.add(current.getString("language"));
				} else {
					bookInfo.add("N/A");
				}
				
				allItemsInfo.add(bookInfo);
			}
			
    		
		} catch (JSONException x) {
			Log.i("jsonExp", x.getMessage());
		} catch (Exception x) {
			//Putting info into LogCat with exception message
			Log.i("myExp", x.getMessage());
		}
		return allItemsInfo;
	}
	
	// always verify the host - dont check for certificate
	final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
	        public boolean verify(String hostname, SSLSession session) {
	                return true;
	        }
	};

	/**
	 * Trust every server - dont check for any certificate
	 */
	private void trustAllHosts() {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
    		public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[] {};
            }

            public void checkClientTrusted(X509Certificate[] chain,
                            String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain,
                            String authType) throws CertificateException {
            }
        } };

        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection
                            .setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
	}
}
